package bigdata.monitor.binlog.service;

import bigdata.monitor.binlog.entity.MonitorRule;
import bigdata.monitor.binlog.mapper.MonitorRuleMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 规则缓存服务
 * - 启动时加载全量规则
 * - 按表分组
 * - 同表内：基础监控（TYPE/ENUM/LENGTH）优先于业务监控（CUSTOM）
 * - 刷新策略：每 30 分钟最多刷新一次（懒加载，非定时调度）
 */
@Slf4j
@Service
public class RuleService {

    @Autowired
    private MonitorRuleMapper monitorRuleMapper;

    // 缓存: tableName -> List<MonitorRule>（已排序）
    private volatile Map<String, List<MonitorRule>> ruleCache = new ConcurrentHashMap<>();

    // 上次刷新时间戳（毫秒）
    private volatile long lastRefreshTime = 0L;

    // 刷新间隔（单位：毫秒）:1800000保证无配置时仍能运行
    @Value("${monitor.rule.refresh-interval-millis:1800000}")
    private long refreshIntervalMillis;

    /**
     * 应用启动时初始化规则缓存
     */
    @PostConstruct
    public void init() {
        refreshRules();
    }

    /**
     * 强制刷新规则缓存（供手动触发或初始化使用）
     */
    public synchronized void refreshRules() {
        try {
            LambdaQueryWrapper<MonitorRule> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(MonitorRule::getEnabled, true);
            List<MonitorRule> allRules = monitorRuleMapper.selectList(lambdaQueryWrapper);

            // 按表分组 + 排序
            Map<String, List<MonitorRule>> grouped = allRules.stream()
                    .collect(Collectors.groupingBy(
                            rule -> rule.getDatabaseName() + "." + rule.getTableName(), // databaseName.tableName
                            Collectors.collectingAndThen(
                                    Collectors.toList(),
                                    list -> {
                                        // 排序: 基础类型在前，CUSTOM 在后
                                        list.sort((r1, r2) -> {
                                            boolean isCustom1 = "CUSTOM".equals(r1.getRuleType());
                                            boolean isCustom2 = "CUSTOM".equals(r2.getRuleType());
                                            if (isCustom1 && !isCustom2) return 1;
                                            if (!isCustom1 && isCustom2) return -1;
                                            return 0;
                                        });
                                        return list;
                                    }
                            )
                    ));

            this.ruleCache = new ConcurrentHashMap<>(grouped);
            this.lastRefreshTime = System.currentTimeMillis();
            log.info("Rule cache refreshed. Tables: {}, Total rules: {}", grouped.size(), allRules.size());
        } catch (Exception e) {
            log.error("Failed to refresh rule cache", e);
        }
    }

    /**
     * 获取指定表的规则列表（线程安全）
     * 若距离上次刷新超过 30 分钟，则自动触发刷新
     */
    public List<MonitorRule> getSortedRulesByKey(String key) {
        // 检查是否需要刷新（双重检查锁）
        if (System.currentTimeMillis() - lastRefreshTime > refreshIntervalMillis) {
            synchronized (this) {
                if (System.currentTimeMillis() - lastRefreshTime > refreshIntervalMillis) {
                    refreshRules();
                }
            }
        }
        return ruleCache.getOrDefault(key, Collections.emptyList());
    }
}
